package GUIMain;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import storage.Field;
import storage.FieldGUI;
import storage.FieldInfo;

import data.ConfigInfo;
import data.ConversionTools;
import data.FilePath;
import data.Reference;
import fileIO.FieldInfoWriter;

public class FieldMappingEditorGUI{
	private static JDialog dialog;
	private static JButton cancelButton;
	private static JButton submitButton;
	private static GridBagConstraints gbc;
	private static JPanel scrollPanel;
	private static JScrollPane scrollPane;
	private static ArrayList<FieldGUI> fieldGUIList;
	private static JTextField titleRowText;
	private static JComboBox mappingCombo;
	private static DefaultComboBoxModel dcbm;
	private static JButton newMapping;
	private static boolean disableListeners = false;
	public static void open() {
		disableListeners = true;
		loadDirectoryList();
		disableListeners = false;
		populateFields();
		GUIFocusManager.add(dialog);
	}
	private static void populateFields(){
		//Populate with current field info
		Object[] keySet = FieldInfo.getAllFieldNames();
		for(int i=0;i<fieldGUIList.size();i++){
			if(i<keySet.length){
				fieldGUIList.get(i).nameField.setText((String)keySet[i]);
				fieldGUIList.get(i).nameField.setEditable(false);
				fieldGUIList.get(i).columnField.setText(ConversionTools.numericToAlpha(FieldInfo.getField((String)keySet[i]).column));
				if(FieldInfo.getFieldType((String)keySet[i]).equals("CNEE")){
					fieldGUIList.get(i).typeCombo.addItem("CNEE");
					fieldGUIList.get(i).originCheckBox.setEnabled(false);
				}else if(FieldInfo.getFieldType((String)keySet[i]).equals("ORIGIN")){
					fieldGUIList.get(i).typeCombo.addItem("ORIGIN");
					fieldGUIList.get(i).originCheckBox.setEnabled(false);
				}else{
					fieldGUIList.get(i).originCheckBox.setEnabled(true);
					fieldGUIList.get(i).originCheckBox.setSelected(FieldInfo.getField((String)keySet[i]).origin);					
				}
				fieldGUIList.get(i).exceptionCheckBox.setEnabled(true);
				fieldGUIList.get(i).exceptionCheckBox.setSelected(FieldInfo.getField((String)keySet[i]).exception);
				fieldGUIList.get(i).typeCombo.setSelectedItem(FieldInfo.getFieldType((String)keySet[i]));
			}else{
				fieldGUIList.get(i).nameField.setText("");
				fieldGUIList.get(i).nameField.setEditable(true);
				fieldGUIList.get(i).columnField.setText("");
				fieldGUIList.get(i).typeCombo.setEditable(false);
				fieldGUIList.get(i).originCheckBox.setSelected(false);
				fieldGUIList.get(i).exceptionCheckBox.setSelected(false);
				fieldGUIList.get(i).typeCombo.setSelectedIndex(-1);
			}
		}
		if((FieldInfo.getTitleRow())>0){
			titleRowText.setText(Integer.toString(FieldInfo.getTitleRow()));
		}else{
			titleRowText.setText("");
		}
	}
	public static void initialize(){
		titleRowText = new JTextField();
		titleRowText.setText(Integer.toString(-1));
		titleRowText.setPreferredSize(new Dimension(60,25));
		cancelButton = new JButton("Cancel");
		submitButton = new JButton("Submit");
		newMapping = new JButton("New Mapping");
		newMapping.setEnabled(false);
		scrollPanel = new JPanel();
		scrollPanel.setLayout(new GridBagLayout());
		scrollPane = new JScrollPane(scrollPanel);
		fieldGUIList = new ArrayList<FieldGUI>();
		dialog = new JDialog();
		dialog.setLayout(new GridBagLayout());
		gbc = new GridBagConstraints();
		dcbm = new DefaultComboBoxModel();
		mappingCombo = new JComboBox(dcbm);
		
		/**
		 * TODO Disable this when mapping switching is finished
		 */
		mappingCombo.setEnabled(false);
		gbc.insets.top = 5;
		gbc.insets.bottom = 5;
		gbc.insets.left = 5;
		gbc.insets.right = 5;
		JPanel scrollPanelContainer = new JPanel();
		scrollPanelContainer.setLayout(new GridBagLayout());
		scrollPanelContainer.setBorder(BorderFactory.createTitledBorder("Fields"));
		JLabel fieldNameLabel = new JLabel("              Field Name       ");
		JLabel columnNoLabel = new JLabel("                 Column     ");
		JLabel fieldTypeLabel = new JLabel("    Field Type  ");
		JLabel checkBoxLabel = new JLabel("    Responsibility   ");
		JLabel EcheckBoxLabel = new JLabel("  Exception Field");
		
		JPanel mapSelectPanel = new JPanel();
		mapSelectPanel.setLayout(new GridBagLayout());
		//Populate Mapping combo
		
		gbc.gridx = 0;
		gbc.gridy = 0;
		mapSelectPanel.add(new JLabel("Current Mapping"),gbc);
		gbc.gridx = 1;
		gbc.gridy = 0;
		mappingCombo.setPreferredSize(new Dimension(300,30));
		mapSelectPanel.add(mappingCombo,gbc);
		gbc.gridx = 2;
		gbc.gridy = 0;
		mapSelectPanel.add(newMapping,gbc);
		gbc.gridx = 0;
		gbc.gridy = 0;
		
		dialog.add(mapSelectPanel,gbc);
		
		JPanel labelPanel = new JPanel();
		labelPanel.setLayout(new GridBagLayout());
		gbc.gridx = 0;
		gbc.gridy = 0;
		labelPanel.add(fieldNameLabel,gbc);
		gbc.gridx = 1;
		gbc.gridy = 0;
		labelPanel.add(columnNoLabel,gbc);
		gbc.gridx = 2;
		gbc.gridy = 0;
		labelPanel.add(fieldTypeLabel,gbc);
		gbc.gridx = 3;
		gbc.gridy = 0;
		labelPanel.add(checkBoxLabel,gbc);
		gbc.gridx = 5;
		labelPanel.add(EcheckBoxLabel,gbc);
		
		gbc.gridx = 0;
		gbc.gridy = 0;
		scrollPanelContainer.add(labelPanel,gbc);
		gbc.gridx = 0;
		gbc.gridy = 1;
		scrollPane.setPreferredSize(new Dimension(600,500));
		scrollPanelContainer.add(scrollPane,gbc);
		
		gbc.gridx = 0;
		gbc.gridy = 1;
		dialog.add(scrollPanelContainer,gbc);
		
		JPanel titlePanel = new JPanel();
		titlePanel.setLayout(new GridBagLayout());
		gbc.gridx =0;
		gbc.gridy =0;
		titlePanel.add(new JLabel("Title Row Number"),gbc);
		gbc.gridx = 1;
		gbc.gridy =0; 
		titlePanel.add(titleRowText,gbc);
		
		gbc.gridx = 0;
		gbc.gridy = 2;
		dialog.add(titlePanel,gbc);
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new GridBagLayout());
		gbc.gridx = 0;
		gbc.gridy = 0;
		buttonPanel.add(cancelButton,gbc);
		gbc.gridx = 1;
		gbc.gridy = 0;
		buttonPanel.add(submitButton,gbc);
		
		gbc.gridx = 0;
		gbc.gridy = 3;
		dialog.add(buttonPanel,gbc);
		
		titleRowText.addFocusListener(new FocusListener(){

			@Override
			public void focusGained(FocusEvent arg0) {
			}
			@Override
			public void focusLost(FocusEvent arg0) {
				//validate contents
				String s = titleRowText.getText();
				if(s!=null && !s.isEmpty()){
					try{
						int rowNum = Integer.parseInt(s);
						if(rowNum<0){
							Exception e = new Exception();
							throw e;
						}else{
							titleRowText.setText(Integer.toString(rowNum));
						}
					}catch(NumberFormatException e){
						JOptionPane.showMessageDialog(null, "Title row number must be an integer!");
						titleRowText.requestFocus();
					}catch(Exception e){
						JOptionPane.showMessageDialog(null, "Enter a valid title row number");
						titleRowText.requestFocus();
					}
				}
			}
		});
		cancelButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				GUIFocusManager.remove();
			}
		});
		newMapping.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				createNewMapping();
			}
		});
		mappingCombo.addItemListener(new ItemListener(){
			@Override
			public void itemStateChanged(ItemEvent arg0) {
				if(!disableListeners &&dcbm.getSelectedItem().toString()!=null){
					FieldInfo.parseFieldColumnTable(FilePath.FIELD_COLUMN_MAPPING_DIRECTORY + "//" + dcbm.getSelectedItem().toString());
					populateFields();
					ConfigInfo.LAST_USED_MAPPING = dcbm.getSelectedItem().toString();
				}
			}
		});
		submitButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				//Check constraints
				ArrayList<Field> output = new ArrayList<Field>();
				ArrayList<String> usedCol = new ArrayList<String>();
				boolean cnee = false;
				boolean error = false;
				for(int i=0;i<fieldGUIList.size();i++){
					String name = fieldGUIList.get(i).nameField.getText();
					String column = fieldGUIList.get(i).columnField.getText();
					Object type = fieldGUIList.get(i).typeCombo.getSelectedItem();
					boolean origin = fieldGUIList.get(i).originCheckBox.isSelected();
					boolean exception = fieldGUIList.get(i).exceptionCheckBox.isSelected();
					if(!name.equals("") || !column.equals("") || (type!=null&&!((String)type).equals(""))){
						if(name.equals("")){
							JOptionPane.showMessageDialog(null, "Name cannot be blank!");
							fieldGUIList.get(i).nameField.requestFocus();
							error = true;
							return;
						}else if(column.equals("")){
							JOptionPane.showMessageDialog(null, "Column number cannot be blank!");
							fieldGUIList.get(i).columnField.requestFocus();
							error = true;
							return;
						}else if(column.length()>2){
							JOptionPane.showMessageDialog(null, "Column number cannot be more than 2 characters long (ex. AA)!");
							fieldGUIList.get(i).columnField.requestFocus();
							error = true;
							return;
						}else if(usedCol.contains(column)){
							JOptionPane.showMessageDialog(null, "Column number already used!");
							fieldGUIList.get(i).columnField.requestFocus();
							error = true;
							return;
						}else if(type == null || ((String)type).equals("")){
							JOptionPane.showMessageDialog(null, "You must select a type!");
							fieldGUIList.get(i).typeCombo.requestFocus();
							error = true;
							return;
						}
						if(type != null && type.equals("CNEE")){
							cnee = true;
						}
						usedCol.add(column);
						output.add(new Field(name,ConversionTools.alphaToNumeric(column),(String)type,origin,exception));
					}
				}
				if(!error){
					if(titleRowText.getText().length()<1){
						int selection = JOptionPane.showConfirmDialog(null, "Do you want to proceed without a Title Row?","Enter Title Row?", JOptionPane.YES_NO_OPTION);
						switch (selection){
						case JOptionPane.NO_OPTION:
							error = true;
							break;
						}
					}
					if(!cnee){
						int selection = JOptionPane.showConfirmDialog(null, "Reports cannot be generated without a CNEE field, enter one now?","Specify CNEE Field", JOptionPane.YES_NO_OPTION);
						switch (selection){
						case JOptionPane.YES_OPTION:
							error = true;
							break;
						}
					}
				}
				//Only write if no errors encountered
				if(!error){
					String fileName ="default";
					if(mappingCombo.getSelectedItem()!=null)
						fileName = mappingCombo.getSelectedItem().toString();
					else{
						//No currently selected mapping, query for a new name
						String b = createNewMapping();
						if(b==""){
							return;
						}else{
							fileName = b;
						}
					}
					System.out.println("Title row text: " + titleRowText.getText());
					FieldInfoWriter.write(fileName, output,titleRowText.getText());

					dcbm.setSelectedItem(fileName);
					FieldInfo.initialize();
					FieldInfo.updateFields();
					JOptionPane.showMessageDialog(null, "Fields saved!");
					GUIFocusManager.remove();
				}
			}
		});
		generateFields();
		
		dialog.setTitle("Edit Field Mapping");
		GUIFocusManager.setDialogProperties(dialog);
	}
	/**
	 * Allows the user to create a new field mapping
	 */
	private static String createNewMapping(){
		String selection = JOptionPane.showInputDialog(null,"Enter a mapping name");
		if(selection!=null && selection.length()>0){
			selection = selection.replace(" ","_");
		}else{
			return "";
		}
		if(!selection.contains(".map")){
			selection += ".map";
		}
		File f = new File(FilePath.FIELD_COLUMN_MAPPING_DIRECTORY +"//" + selection);
		if(f.exists()){
			int choice = JOptionPane.showConfirmDialog(null, "A mapping with this name already exists, do you want to overwrite?");
			if(choice== JOptionPane.OK_OPTION){
				f.delete();
			}else{
				return "";
			}
		}
		try {
			f.createNewFile();
		} catch (IOException e1) {
			JOptionPane.showMessageDialog(null, "Mapping cannot be saved to directory: " + f.getAbsolutePath());
			return "";
		}
		loadDirectoryList();
		return f.getName();
	}
	private static void generateFields(){
		//create 100 fields
		for(int i=0;i<75;i++){
			FieldGUI tempFieldGUI = new FieldGUI();
			
			gbc.gridy = i;
			gbc.gridx = 0;
			JLabel countLabel = new JLabel(Integer.toString(i+1));
			scrollPanel.add(countLabel,gbc);
			gbc.gridx = 1;
			tempFieldGUI.nameField.setPreferredSize(new Dimension(125,25));
			scrollPanel.add(tempFieldGUI.nameField,gbc);
			gbc.gridx = 2;
			tempFieldGUI.columnField.setPreferredSize(new Dimension(60,25));
			scrollPanel.add(tempFieldGUI.columnField,gbc);
			gbc.gridx = 3;
			tempFieldGUI.typeCombo.setPreferredSize(new Dimension(100,25));
			tempFieldGUI.typeCombo = new JComboBox(Reference.fieldTypeList.toArray());
			tempFieldGUI.typeCombo.removeItem("KEY");
			tempFieldGUI.typeCombo.insertItemAt("", 0);
			tempFieldGUI.typeCombo.setSelectedIndex(0);

			scrollPanel.add(tempFieldGUI.typeCombo,gbc);
			gbc.gridx = 4;
			scrollPanel.add(tempFieldGUI.originCheckBox,gbc);
			gbc.gridx = 5;
			scrollPanel.add(tempFieldGUI.exceptionCheckBox,gbc);
			fieldGUIList.add(tempFieldGUI);
		}
	}
	private static void loadDirectoryList(){
		dcbm.removeAllElements();
		File f = new File(FilePath.FIELD_COLUMN_MAPPING_DIRECTORY);
		if(!f.isDirectory()){
			f.mkdirs();
		}else{
			String[] dirList = f.list();
			for(int i=0;i<dirList.length;i++){
				dcbm.addElement(dirList[i]);
			}
		}
	}
}
